OOP Video
Code: https://ide.geeksforgeeks.org/zjNlROYaVE
Track: Covers the topic of "Object-Oriented Programming in C++".
Objective: Along with the theories focusing on OOP in C++, the track provides video lectures for easier understanding. It also tests the candidate's clarity in the subject by introducing contests in the form of a quiz and weekly contests.
Track Content:
Assessment: The tracks assess the students through regular weekly contests.
Important Topics:
Class
A class is a user-defined blueprint or prototype from which real-world objects are created. It represents the set of properties or methods that are common to all objects of one type.
Object
It is a basic unit of Object Oriented Programming and represents the real-life entities. A typical Java program creates many objects, which as you know, interact by invoking methods.
Inheritance
The capability of a class to derive properties and characteristics from another class is called Inheritance. Inheritance is one of the most important feature of Object Oriented Programming.
Polymorphism
The word polymorphism means having many forms. In simple words, we can define polymorphism as the ability of a message to be displayed in more than one form.
Abstraction
Data Abstraction is the property by virtue of which only the essential details are displayed to the user. The trivial or the non-essentials units are not displayed to the user. Ex: A car is viewed as a car rather than its individual components.Advantages of Abstraction
Encapsulation
Encapsulation is defined as the wrapping up of data under a single unit. It is the mechanism that binds together the code and the data it manipulates. Another way to think about encapsulation is that it is a protective shield that prevents the data from being accessed by the code outside this shield.Encapsulation vs Data Abstraction
Class Definition and Object Instantiation
The syntax for class declaration is as:class < class-name > {
< access-modifier >:
//data-members
//constructors
//member-functions
//destructors
}; //don't forget the semi-colon here !!
Each of the above terms (constructors, destructors, access-modifiers etc.) will be explained in detail afterwards.
#include <bits/stdc++.h>
using namespace std;
class Employee { //Class Declaration
public:
string id, name;
int years; //experience (in years)
Employee(string id, string name, int years) {
this->id = id;
this->name = name;
this->years = years;
}
void work() {
cout << "Employee: " << this->id << " is working\n";
}
};
int main()
{
//Class Instantiation (Direct)
Employee emp("GFG123", "John", 3);
//Class Instantiation (Indirect)
Employee *emp_ptr = new Employee("GFG456", "James", 4);
cout << "Employee ID: " << emp.id << endl;
cout << "Name: " << emp.name << endl;
cout << "Experience (in years): " << emp.years << endl;
emp.work();
cout << endl;
cout << "Employee ID: " << emp_ptr->id << endl;
cout << "Name: " << emp_ptr->name << endl;
cout << "Experience (in years): " << emp_ptr->years << endl;
emp_ptr->work();
return 0;
}Employee ID: GFG123
Name: John
Experience (in years): 3
Employee: GFG123 is working
Employee ID: GFG456
Name: James
Experience (in years): 4
Employee: GFG456 is working
Data Members
Data Members are the identifiers that describe the characteristics and hold important data related to the class. In our Employee class, we have id, name, years as the data members. Data members can be anything from primitive data-types (int, char, double, etc.) to collections (arrays, strings, etc.) to user-defined data-types (structs, unions, even other class objects, etc.). Anything that can hold data value can be a data-member.Member Functions
Member Functions/Methods are class-functions/methods which describe the behavior of the class. i.e. what kind of operation we can perform with objects of this class. e.g. In our Employee example, work() is a member function. Member functions in C++ can be defined inside/outside the class, however, it is mandatory to have prototype declaration inside the class if go for an outside-the-class definition. e.g.Employee: GFG123 is working
Abstraction using Access Modifiers
There are 3 types of access modifiers in C++, which we discuss in detail below:Radius is: 5.5
Area is: 94.985
prog.cpp: In function 'int main()':The output of the above program will be a compile-time error because we are not allowed to access the private data members of a class directly outside the class. If we comment out the obj.radius = 1.5; statement, then the program compiles fine. We can access the private data members of a class indirectly using the public member functions of the class. Below program explains how to do this:
prog.cpp:9:16: error: 'double Circle::radius' is private
double radius;
^
prog.cpp:27:9: error: within this context
obj.radius = 1.5;
^
Radius: 5
Area: 78.5
id_protected is: 81
How constructors are different from a normal member function?
A constructor differs from member-functions in the following ways:Default Constructor
It is not mandatory for the programmer to write a constructor for each class. C++ by default provides a default constructors with no parameters, and no statements for the body. Much like being:Employee() {} //as per our example
Constructor Overloading
We need to first get a grasp of overloading first, which is explained as:
#include <bits/stdc++.h>
using namespace std;
class Employee {
public: // public access-modifier
string id, name;
int years;
Employee()
{
id = "";
name = "";
years = 0;
}
// Overloaded constructor
Employee(string id, string name, int years)
{
this->id = id;
this->name = name;
this->years = years;
}
// Overloaded constructor
Employee(string id, string name)
{
this->id = id;
this->name = name;
years = 0;
}
void getDetails()
{
cout << "ID: " << id << ", Name: " << name
<< ", Experience: " << years << endl;
}
};
int main()
{
// 1st constructor is called
Employee emp1;
// 2nd constructor is called
Employee emp2("GFG123", "John", 4);
// 3rd constructor is called
// where years is 0 (no experience for a fresher)
Employee fresher("GFG456", "James");
emp1.getDetails();
emp2.getDetails();
fresher.getDetails();
return 0;
}ID:, Name:, Experience: 0
ID: GFG123, Name: John, Experience: 4
ID: GFG456, Name: James, Experience: 0
Member Initializer List
Member Initialization List is a new syntactic construct introduced in modern C++, which allows us to write concise initialization code in constructors. The basic syntax is as:Constructor(< arguments >) : < mem1(arg1), mem2(arg2), ...., > {
//additional code to execute after initialization
}
ID: GFG123, Name: John, Experience: 4
Constructor Chaining (Delegation)
Constructor chaining/delegation is the process of re-using constructors by others to avoid writing repeated code. This is done by calling one constructor to set common values by other constructors. As an example:ID: GFG123, Name: John, Experience: 4
Destructors
Destructors like constructors are special members of a class that is executed once the lifetime of the object expires. It is like the final clean-up code required before deleting the class instance. Unlike JAVA, C++ doesn't perform automatic garbage collection. Hence, it often becomes the responsibility of the developer to de-allocate memory (not required further). A classic example:Hello World
~ Classname { //clean-up code }
The above code with destructors:Copy Constructor
A copy constructor is a member function that initializes an object using another object of the same class. A copy constructor has the following general function prototype:Classname (const Classname &object);Copy constructor, in general, is not required to be defined by the user, as the compiler automatically provides a default copy constructor. However, this default copy constructor performs a shallow copy only (i.e. copy values only). This results in pointer variables pointing the same instances upon copy. We need to define our own copy constructor only if an object has pointers or any runtime allocation of the resource like file handle, a network connection.etc.


#include <bits/stdc++.h>
using namespace std;
class Array {
public:
int n;
int* ref;
Array(int n)
: n(n)
{
ref = new int[n];
for (int i = 0; i < n; i++)
*(ref + i) = i;
}
};
int main()
{
Array arr1(10);
// copy constructor called
// at this point
Array arr2 = arr1;
// changing n-value in 2nd instance
arr2.n = 5;
// changing array-values in 2nd instance
for (int i = 0; i < 10; i++)
*(arr2.ref + i) *= 2;
cout << "n-value of 1st instance: " << arr1.n << endl;
cout << "Array values of 1st instance:\n";
for (int i = 0; i < 10; i++)
cout << *(arr1.ref + i) << " ";
cout << endl;
return 0;
}n-value of 1st instance: 10
Array values of 1st instance:
0 2 4 6 8 10 12 14 16 18
#include <bits/stdc++.h>
using namespace std;
class Array {
public:
int n;
int* ref;
Array(int n)
: n(n)
{
ref = new int[n];
for (int i = 0; i < n; i++)
*(ref + i) = i;
}
// copy-contructor definition
Array(const Array& obj)
: n(obj.n)
{
ref = new int[n];
for (int i = 0; i < n; i++)
*(ref + i) = *(obj.ref + i);
}
};
int main()
{
Array arr1(10);
// copy constructor called
// at this point
Array arr2 = arr1;
// changing n-value in 2nd instance
arr2.n = 5;
// changing array-values in 2nd instance
for (int i = 0; i < 10; i++)
*(arr2.ref + i) *= 2;
cout << "n-value of 1st instance: " << arr1.n << endl;
cout << "Array values of 1st instance:\n";
for (int i = 0; i < 10; i++)
cout << *(arr1.ref + i) << " ";
cout << endl;
return 0;
}n-value of 1st instance: 10
Array values of 1st instance:
0 1 2 3 4 5 6 7 8 9
#include <bits/stdc++.h>
using namespace std;
class Employee {
public:
string id, name;
int years;
//'this' keyword here retrieves the object's
//instance variables: id, name, years hidden
//by their same-name local counterparts
Employee(string id, string name, int years) {
this->id = id;
this->name = name;
this->years = years;
}
//here we don't need to use 'this' keyword
//explicitly as their are no local variables
//with the same name. So, compiler automatically
//deduces it as instance variables
void printDetails() {
cout << "ID: " << id
<< ", Name: " << name
<< ", Experience: " << years;
}
};
int main()
{
Employee emp("GFG123", "John", 4);
emp.printDetails();
return 0;
}ID: GFG123, Name: John, Experience: 4
#include <bits/stdc++.h>
using namespace std;
class Employee {
private:
string id, name;
int years;
public:
Employee setId(string id) {
this->id = id;
return *this;
}
Employee setName(string name) {
this->name = name;
return *this;
}
Employee setYears(int years) {
this->years = years;
return *this;
}
void printDetails() {
cout << "ID: " << id
<< ", Name: " << name
<< ", Experience: " << years;
}
};
int main()
{
Employee emp;
emp.setId("GFG123").setName("John").setYears(4).printDetails();
return 0;
}ID: GFG123, Name: John, Experience: 4
Static data-members
Declaring a data member in a class as static gives it class-scope. i.e. The variable no longer remains specific and bound to one particular object instance. Thereafter, changing the value from one instance reflects over all the instances. As an example:Access from instance: 1
Access from Class: 1
t1.x: 5
t2.x: 5
Test::x: 5
Static member-functions
Static Member Functions are similar to the static data-members implying that they too have class-scope. In addition to that, they are allowed to access only other static fields (data & member). However, they can be called using object instances. (i.e. obj.static_method() is valid). Some important points regarding static member functions are given below:5
Friend Class
A Friend Class can access private and protected members of other classes in which it is declared as a friend. It is sometimes useful to allow a particular class to access private members of other classes.e.g.A LinkedList class may be allowed to access private members of Node.
#include <bits/stdc++.h>
using namespace std;
class Node
{
private:
int key;
Node *next;
Node(int key) : key(key), next(nullptr) {}
public:
friend class LinkedList;
};
class LinkedList
{
public:
Node *root;
LinkedList(int key) {
root = new Node(key);
}
void insert(int key) {
Node *trav = root;
while (trav->next != nullptr)
trav = trav->next;
trav->next = new Node(key);
}
void print() {
Node *trav = root;
while (trav != nullptr) {
cout << trav->key << " ";
trav = trav->next;
}
cout << endl;
}
};
int main()
{
LinkedList list(0);
list.insert(1);
list.insert(2);
list.insert(3);
list.insert(4);
list.print();
return 0;
}0 1 2 3 4
Friend Function
Like a friend class, a friend function can be given special access to private and protected members. A friend function can be:
#include <bits/stdc++.h>
using namespace std;
//forward-declaration is
//necessary for usage in A
//as B is not defined yet
class B;
class A
{
public:
void showB(B &x);
};
class B
{
private:
int b;
public:
B() : b(0) {}
//Friend function Declaration
friend void A::showB(B &x);
};
//Friend Member Function Definition
void A::showB(B &x)
{
cout << "B::b = " << x.b;
}
int main()
{
A a;
B x;
a.showB(x);
return 0;
}B::b = 0
A::a=0
11
30
12 + i9
12 + i9
0.4
x = 20, y = 20
x = 30, y = 0
Overloading
Overloading is a feature that allows a class to have multiple methods with the same name, the only difference lies in their list of arguments. i.e. The argument list for each of the methods differ, and it helps the compiler or the run-time environment to identify which method to call depending upon the parameters passed. Constructors can be overloaded too.
#include <bits/stdc++.h>
using namespace std;
class Math
{
public:
//Overloaded add() methods
static int add(int x, int y) { return x + y; }
static void add(int a[], int b[], int sum[], int n) {
for (int i=0;i<n;i++)
//use the 1st form to get addition of
//two numbers
sum[i] = add(a[i], b[i]);
}
//Overloaded mul() methods
static int mul(int x, int y) { return x * y; }
static void mul(int a[], int b[], int prod[], int n) {
for (int i=0;i<n;i++)
//use the 2nd form to get product
//of two numbers
prod[i] = mul(a[i], b[i]);
}
};
int main()
{
int a[] = {1, 2, 3, 4, 5};
int b[] = {9, 8, 7, 6, 5};
int sum[5], prod[5];
Math::add(a, b, sum, 5);
Math::mul(a, b, prod, 5);
for (int i=0; i<5; i++)
cout << sum[i] << " ";
cout << endl;
for (int i=0; i<5; i++)
cout << prod[i] << " ";
cout << endl;
return 0;
}10 10 10 10 10
9 16 21 24 25
1st form called: 5
2nd form called: 5
3rd form called: 5
Overriding
Inheritance allows Derived Classes to inherit Base class data-members as well as member functions. Thus, if we call base class function with derived class instance, it would run perfectly:I'm Base Class!!
I'm Base Class!!
I'm Base Class!!
I'm Derived Class!!
I'm Base Class!!
I'm Derived Class!!
Run-time Polymorphism
Consider a situation where we have Derived Class which has overridden some method of the Base Class. Polymorphism allows us to have a Base Class reference a Derived Class Object. Then, in such a case, which function to call (Base or Derived) is decided at run-time, as the compiler is unable to resolve which one to call during compilation. Below is a classic example of Run-time Polymorphism:I'm Base

B's constructor called
A's constructor called
C's constructor called
#include <bits/stdc++.h>
using namespace std;
class Person
{
// Data members of person
public:
Person(int x) {
cout << "Person::Person(int ) called" << endl;
}
};
class Faculty : public Person
{
// data members of Faculty
public:
Faculty(int x) : Person(x) {
cout << "Faculty::Faculty(int) called" << endl;
}
};
class Student : public Person
{
// data members of Student
public:
Student(int x) : Person(x) {
cout << "Student::Student(int) called" << endl;
}
};
class TA : public Faculty, public Student
{
public:
TA(int x): Student(x), Faculty(x) {
cout << "TA::TA(int) called" << endl;
}
};
int main() {
TA ta(30);
return 0;
}Person::Person(int ) called
Faculty::Faculty(int) called
Person::Person(int ) called
Student::Student(int) called
TA::TA(int) called

Person::Person() called
Faculty::Faculty(int) called
Student::Student(int) called
TA::TA(int) called
#include <bits/stdc++.h>
using namespace std;
class Person
{
public:
Person(int x) { cout << "Person::Person(int) called" << endl; }
Person() { cout << "Person::Person() called" << endl; }
};
class Faculty : virtual public Person
{
public:
Faculty(int x) : Person(x) {
cout << "Faculty::Faculty(int) called" << endl;
}
};
class Student : virtual public Person
{
public:
Student(int x) : Person(x) {
cout << "Student::Student(int) called" << endl;
}
};
class TA : public Faculty, public Student {
public:
TA(int x) : Student(x), Faculty(x), Person(x) {
cout << "TA::TA(int) called" << endl;
}
};
int main() {
TA ta(30);
return 0;
}Person::Person(int) called
Faculty::Faculty(int) called
Student::Student(int) called
TA::TA(int) called
prog.cpp: In function 'int main()':Above code generates compilation-error because we tried to access data-member x for instance b (which is private).
prog.cpp:10:9: error: 'int B::x' is private
int x; // x is private
^
prog.cpp:19:15: error: within this context
cout << b.x << endl;
^
prog.cpp: In function 'int main()':The above code generates compilation error because of the access statement d1.x. Since we didn't specify the access-modifier for the Base class, x became private in Derived Class.
prog.cpp:8:13: error: 'int Base::x' is inaccessible
int x; // x is public
^
prog.cpp:26:16: error: within this context
cout << d1.x << endl;
^
A | A function can only be declared a friend by a class itself. |
![]() | Friend functions are not members of a class, they are associated with it. |
![]() | Friend functions are members of a class. |
D | It can have access to all members of the class, even private ones. |
Your submitted response was incorrect.